<template>
  <div class="container" ref="container">
    <div class="scroll-wrapper" :style="style">
      <div v-for="(item, index) in scrollList" :key="index" class="item">
        {{ item }}
      </div>
    </div>
  </div>
</template>

<script>
// 虚拟列表-fix超长列表渲染优化
export default {
  name: 'virtualList',
  data () {
    return {
      list: [],
      startIndex: 0,
      endIndex: 60,
      paddingTop: 0,
      paddingBottom: 0,
      allHeight: 0
    }
  },
  beforeCreate () {},
  created () {
    this.add()
  },
  beforeMount () {},
  mounted () {
    this.initListener()
  },
  beforeUpdate () {},
  updated () {},
  beforeDestroy () {},
  destroyed () {},
  methods: {
    add () {
      let arr = new Array(50000).fill(0)
      arr = arr.map((item, index) => {
        return `虚拟列表dome${index}`
      })
      this.list = [...this.list, ...arr]
    },
    initListener () {
      const container = this.$refs.container
      container.addEventListener('scroll', () => {
        const top = container.scrollTop
        this.startIndex = Math.floor(top / 30)
        this.endIndex = this.startIndex + 60

        this.paddingTop = top
        if (this.endIndex >= this.list.length - 1) {
          this.paddingBottom = 0
          return
        }
        this.paddingBottom = this.allHeight - 600 - top
      })
    }
  },
  computed: {
    scrollList () {
      return this.list.slice(this.startIndex, this.endIndex)
    },
    style () {
      return {
        paddingTop: this.paddingTop + 'px',
        paddingBottom: this.paddingBottom + 'px'
      }
    }
  },
  watch: {
    list (val) {
      const valLen = val.length
      this.allHeight = valLen * 30
      this.paddingBottom = this.allHeight - this.scrollList.length * 30
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.container {
  width: 300px;
  height: 600px;
  overflow: auto;
  border: 1px solid;
  margin: 0px auto;
}
.scroll-wrapper {
  box-sizing: border-box;
}
.item {
  height: 29px;
  line-height: 30px;
  border-bottom: 1px solid #aaa;
  padding-left: 20px;
}
</style>
